﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Diagnostics;

namespace PaiPaiImage
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private System.Collections.ObjectModel.ObservableCollection<FileInfoViewModel> files = new System.Collections.ObjectModel.ObservableCollection<FileInfoViewModel>();

        private int newWidth = 730;
        private bool noResizeWhenSmall = true;
        private int maxFileSizeInKB = 1024;
        private bool spiltImage = true;
        private string outDir = null;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.dgFiles.ItemsSource = this.files;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            FileInfoViewModel fi = (e.Source as Hyperlink).DataContext as FileInfoViewModel;
            if (fi == null)
            {
                return;
            }

            this.files.Remove(fi);
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.C)
            {
                this.btnClear_Click(null, null);
            }
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            this.files.Clear();
            this.dgNewFiles.ItemsSource = null;
        }

        private bool UpdateUIToSource()
        {
            try
            {
                this.newWidth = int.Parse(this.tbNewWidth.Text.Trim());
                this.noResizeWhenSmall = this.cbSmallNoResize.IsChecked.Value;
                this.spiltImage = this.cbSpilt.IsChecked.Value;
                if (this.spiltImage)
                    this.maxFileSizeInKB = int.Parse(this.tbSizeInKB.Text.Trim());
                this.outDir = this.cbbOutput.Text.Trim();
                return true;
            }
            catch
            {
                throw new Exception("请输入新的图片宽度与文件大小上限,再进行操作");
            }
        }

        private void Window_Drop(object sender, DragEventArgs e)
        {
            try
            {
                this.UpdateUIToSource();
                string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
                if (files == null)
                {
                    return;
                }

                foreach (string file in files)
                {
                    if (System.IO.Directory.Exists(file))
                    {
                        MessageBox.Show(this, "路径是文件夹:" + file, "不能添加", MessageBoxButton.OK, MessageBoxImage.Error);
                        continue;
                    }
                    if (this.files.LastOrDefault(obj => obj.Path.Equals(file, StringComparison.OrdinalIgnoreCase)) == null && System.IO.File.Exists(file))
                    {
                        this.files.Add(this.CreateFileInfoViewModel(file, false));
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnProcess_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (this.files.Count < 1)
                {
                    MessageBox.Show(this, "没有要处理的文件");
                    return;
                }
                this.UpdateUIToSource();
                if (string.IsNullOrWhiteSpace(this.outDir))
                {
                    MessageBox.Show(this, "输出文件夹为空");
                    return;
                }

                string outputDir = System.IO.Path.Combine(this.files[0].Path.Substring(0, this.files[0].Path.LastIndexOf('\\')), this.outDir + "\\");
                if (System.IO.Directory.Exists(outputDir))
                {
                    System.IO.Directory.Delete(outputDir, true);
                }
                System.IO.Directory.CreateDirectory(outputDir);
                bool autoRename = this.chkAutoRename.IsChecked.Value;
                Task.Factory.StartNew(() => this.ProcessImages(this.files.ToArray(), outputDir, autoRename));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private FileInfoViewModel CreateFileInfoViewModel(string filePath, bool checkFielSize)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            Brush brush = null;
            string state = (fileInfo.Length / 1024 > maxFileSizeInKB ? "图片大于" : "图片小于") + maxFileSizeInKB + "KB";

            uint width = 0, height = 0;

            if (ImageToolKit.Net.ImageToolKitNative.ImageGetSize(filePath, ref width, ref height) == false)
            {
                MessageBox.Show(this, filePath, "无法获取图片长宽信息", MessageBoxButton.OK, MessageBoxImage.Error);
                brush = Brushes.Red;
            }

            if (checkFielSize && fileInfo.Length / 1024 > maxFileSizeInKB)
            {
                brush = Brushes.Red;
            }
            FileInfoViewModel item = new FileInfoViewModel(filePath, width + " X " + height, fileInfo.Length / 1024, state, brush);
            return item;
        }

        private bool ProcessFile(string outputDir, FileInfoViewModel file)
        {
            FileInfo fileInfo = new FileInfo(file.Path);
            
            string newPath = outputDir + fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf(".")) + ".jpg";

            if (File.Exists(newPath))
            {
                File.Delete(newPath);
            }

            if (this.noResizeWhenSmall && file.Width < this.newWidth)
            {
                File.Copy(file.Path, newPath);
            }
            else
            {
                if (ImageToolKit.Net.ImageToolKitNative.ImageResize(file.Path, newPath, this.newWidth) == false)
                {
                    return false;
                }
            }

            if (File.Exists(newPath) == false)
            {
                return false;
            }

            if (this.spiltImage == false)
            {
                return true;
            }

            fileInfo = new FileInfo(newPath);
            if (fileInfo.Length > this.maxFileSizeInKB * 1024)
            {
                int count = 0;
                if (this.maxFileSizeInKB > 300)
                {
                    count = (int)((fileInfo.Length / 1024 + this.maxFileSizeInKB - 1) / (this.maxFileSizeInKB - 200));
                }
                else
                {
                    count = (int)(fileInfo.Length / 1024 + this.maxFileSizeInKB - 1) / (this.maxFileSizeInKB);
                }
                if (ImageToolKit.Net.ImageToolKitNative.ImageSpilte(newPath, fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf(".")), outputDir, count))
                {
                    File.Delete(newPath);
                    Thread.Sleep(50);
                }
            }
            return true;
        }

        private void ProcessImages(FileInfoViewModel[] files, string outputDir, bool autoRename)
        {
            try
            {
                List<string> ouputFiles = new List<string>();
                FileInfo[] fileInfos = files.Select(obj => new FileInfo(obj.Path)).ToArray();
                this.Dispatcher.Invoke(new Action(() =>
                {
                    this.btnProcess.IsEnabled = false;
                    this.tbProcess.Text = "处理中...";
                    foreach (var file in files)
                    {
                        file.State = "等待处理";
                    }
                }));

                for (int i = 0; i < files.Length; i++)
                {
                    this.Dispatcher.Invoke(new Action(() => files[i].State = "正在处理"));
                    bool ret = this.ProcessFile(outputDir, files[i]);
                    if (ret)
                    {
                        ouputFiles.AddRange(System.IO.Directory.GetFiles(outputDir, fileInfos[i].Name.Substring(0, fileInfos[i].Name.LastIndexOf('.')) + "*"));
                    }
                    this.Dispatcher.Invoke(new Action(() =>
                        {
                            files[i].State = ret ? "处理成功" : "处理失败";
                            files[i].Background = ret ? null : Brushes.Red;
                        }));
                }

                fileInfos = ouputFiles.Select(obj => new FileInfo(obj)).ToArray();

                if (autoRename)
                {
                    string[] newFiles = new string[fileInfos.Length];
                    //第一步将每个文件重名为临时加编号
                    for (int i = 0; i < fileInfos.Length; i++)
                    {
                        newFiles[i] = fileInfos[i] + "临时文件_FFF+" + i;
                        fileInfos[i].MoveTo(newFiles[i]);
                    }

                    for (int i = 0; i < newFiles.Length; i++)
                    {
                        try
                        {
                            fileInfos[i].MoveTo(fileInfos[i].DirectoryName + "\\" + (i + 1).ToString("D2") + ".jpg");
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                }

                this.Dispatcher.Invoke(new Action(() =>
                    {
                        var newFileInfos = fileInfos.Select(obj => this.CreateFileInfoViewModel(obj.FullName, true)).ToArray();
                        this.dgNewFiles.ItemsSource = newFileInfos;
                        if (this.spiltImage && newFileInfos.Any(obj => obj.SizeInKB > this.maxFileSizeInKB))
                        {
                            MessageBox.Show(this, "请注意有文件在处理过后，大小超过:" + (this.maxFileSizeInKB) + "KB", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                this.Dispatcher.Invoke(new Action(() =>
                {
                    this.btnProcess.IsEnabled = true;
                    this.tbProcess.Text = "已完成";
                }));
            }
        }
    }
}
